package com.gframework.boot.mvc.controller.protocal.basic;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;

import com.gframework.autoconfigure.mvc.MvcProperties;
import com.gframework.boot.mvc.controller.errcode.ErrorCodeException;
import com.gframework.boot.mvc.controller.protocal.RestResponseHandler;

/**
 * ServerResponse对象结构的rest前后端统一通讯格式处理类，也是默认的 {@link RestResponseHandler} 接口处理子类.
 * <p>通过自定义 {@link RestResponseHandler} 接口子类可以覆盖本类默认配置。
 * 
 * @since 2.0.0
 * @author Ghwolf
 *
 */
@SuppressWarnings("deprecation")
public class ServerResponseRestHandler implements RestResponseHandler {
	private static final Logger logger = LoggerFactory.getLogger(ServerResponseRestHandler.class);
	/**
	 * 利用post进行复杂查询请求时的特定路径后缀
	 */
	private final String postSearchUriSuffix ;
	
	/**
	 * 是否在controller返回正常结果时，不进行包装
	 */
	private final boolean noPackagingWhenSuccess ;
	/**
	 * 是否在post请求成功后http状态返回201而不是200
	 */
	private final boolean return201WhenPost;
	
	public ServerResponseRestHandler(MvcProperties properties) {
		Assert.notNull(properties.getPostSearchUriSuffix(),"post请求方法执行查询操作规范uri后缀不能为空！");
		this.noPackagingWhenSuccess = properties.isNoPackagingWhenSuccess();
		this.return201WhenPost = properties.isReturn201WhenPost();
		this.postSearchUriSuffix = properties.getPostSearchUriSuffix();
	}
	
	
	@Override
	public Object handleResult(Throwable e,HttpServletRequest request,HttpServletResponse response) {
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		if (e instanceof ErrorCodeException) {
			ErrorCodeException statusExp = (ErrorCodeException) e;
			response.setStatus(statusExp.getHttpCode());
			return statusExp.response();
		} else {
			setHttpStatusIf20x(response,500);
			ServerResponse body = new ServerResponse();
			body.setStatus(500);
			body.setMessage(e.getMessage() == null ? e.toString() : e.getMessage());
			logger.error(e.getMessage(), e);
			return body;
		}
	}

	@Override
	public Object handleResult(Object obj,HttpServletRequest request,HttpServletResponse response) {
		if (obj instanceof ServerResponse) {
			return obj ;
		}
		if (obj instanceof ErrorCodeException) {
			ErrorCodeException e = (ErrorCodeException) obj ;
			response.setStatus(e.getHttpCode());
			return e.response();
		}
		if (this.return201WhenPost && request.getMethod().equals("POST") && !request.getRequestURI().endsWith(this.postSearchUriSuffix)) {
			response.setStatus(201);
		}
		if (this.noPackagingWhenSuccess) {
			return obj ;
		}
		return new ServerResponse(HttpStatus.OK.value(),HttpStatus.OK.getReasonPhrase(),obj);
	}

	@Override
	public Object handleResult(int httpStatus,HttpServletRequest request,HttpServletResponse response) {
		HttpStatus hs = HttpStatus.resolve(httpStatus);
		response.setStatus(hs == null ? HttpStatus.INTERNAL_SERVER_ERROR.value() : httpStatus);
		if (hs == null) {
			response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
			return new ServerResponse(httpStatus,"服务器出现未知错误！");
		} else {
			return handleResult(hs,request,response);
		}
	}

	@Override
	public Object handleResult(HttpStatus httpStatus,HttpServletRequest request,HttpServletResponse response) {
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		response.setStatus(httpStatus.value());
		return new ServerResponse(httpStatus.value(),httpStatus.getReasonPhrase());
	}

	private void setHttpStatusIf20x(HttpServletResponse response,int sc){
		if (response.getStatus() / 100 == 2) {
			response.setStatus(sc);
		}
	}
	
}
